const db=require('../db/index.js')
const bcrypt = require('bcryptjs')
const jwt = require('jsonwebtoken')
const config = require('../config')
//得到伙伴信息
const queryDb = (sql, params) => {
  return new Promise((resolve, reject) => {
    db.query(sql, params, (err, result) => {
      if (err) reject(err); // 出错时 reject
      else resolve(result); // 成功时 resolve 结果
    });
  });
};
//获取伙伴信息
const getPartnerInfo = async (req, res) => {
  try {
    // 1. 参数校验（保持不变）
    const { userId } = req.query;
    if (!userId) {
      return res.status(401).json({ 
        status: 401, 
        message: "请先登录再获取伙伴信息" 
      });
    }

    // 2. 查询伙伴关系（改用 queryDb，注意：queryDb 直接返回 result，无需解构 [result]）
    const queryPartnersSql = `
      (SELECT 
        p.partner_id AS id,
        u.nickname,
        u.avatar,
        u.major,  -- 专业
        u.intro,  -- 个人简介
        p.created_at AS becomePartnerTime,
        FALSE AS is_initiated
       FROM partners p
       JOIN users u ON p.partner_id = u.id
       WHERE p.user_id = ? AND p.status = 1)
      
      UNION
      
      (SELECT 
        p.user_id AS id,
        u.nickname,
        u.avatar,
        u.major,  -- 专业
        u.intro,  -- 个人简介
        p.created_at AS becomePartnerTime,
        TRUE AS is_initiated
       FROM partners p
       JOIN users u ON p.user_id = u.id
       WHERE p.partner_id = ? AND p.status = 1)
      
      ORDER BY becomePartnerTime DESC
      LIMIT 100
    `;

    // 关键修改：用 queryDb 替代 db.promise().query，无需解构 [result]
    const partnersResult = await queryDb(queryPartnersSql, [userId, userId]);
    
    if (partnersResult.length === 0) {
      return res.status(200).json({
        status: 200,
        message: "暂无学习伙伴，快去邀请同学吧",
        data: []
      });
    }

    // 3. 代码层面去重（保持不变）
    const uniquePartners = [];
    const seenIds = new Set();
    for (const partner of partnersResult) {
      if (!seenIds.has(partner.id)) {
        seenIds.add(partner.id);
        uniquePartners.push(partner);
      }
    }

    // 4. 查询伙伴学习信息（改用 queryDb）
    const partnerIds = uniquePartners.map(p => p.id);
    const queryInfoSql = `
      SELECT 
        p.user_id,
        p.study_time,
        ucp.selected_course_names
      FROM preferences p
      JOIN user_complete_profile ucp ON p.user_id = ucp.user_id
      WHERE p.user_id IN (?)
    `;

    // 关键修改：用 queryDb 替代 db.promise().query，无需解构 [result]
    const infoResult = await queryDb(queryInfoSql, [partnerIds]);
    
    // 5. 构建学习信息Map（保持不变）
    const partnerInfoMap = new Map(
      infoResult.map(info => [info.user_id, info])
    );

    // 6. 组装最终数据（保持不变）
    const partnerList = uniquePartners.map(partner => ({
      partnerId: partner.id,
      nickname: partner.nickname,
      avatar: partner.avatar,
      major: partner.major || "未填写",
      intro: partner.intro || "暂无简介",
      studyTime: partnerInfoMap.get(partner.id)?.study_time || "暂无设置",
      selectedCourses: partnerInfoMap.get(partner.id)?.selected_course_names || "暂无课程",
      becomePartnerTime: partner.becomePartnerTime,
      isInitiated: partner.is_initiated
    }));

    res.status(200).json({
      status: 200,
      message: "伙伴信息获取成功",
      data: partnerList
    });

  } catch (err) {
    console.error("获取伙伴信息异常:", err.stack);
    res.status(500).json({ 
      status: 500, 
      message: "获取伙伴信息失败：服务器内部错误",
      error: process.env.NODE_ENV === 'development' ? err.message : undefined
    });
  }
};
//得到邀请信息
const getInviteInfo = async (req, res) => {
  try {
    // 1. 解析并校验参数（保持不变）
    const { userId } = req.query;
    if (!userId || isNaN(Number(userId))) {
      return res.status(400).json({
        status: 400,
        message: "用户ID（userId）不能为空且必须是有效数字"
      });
    }
    const receiverId = Number(userId);

    // 2. 查询未读邀请（改用 queryDb，无需解构 [result]）
    const queryInvitesSql = `
      SELECT 
        m.id AS inviteId,
        m.content AS inviteContent,
        m.is_read AS isRead,
        m.created_at AS sendTime
      FROM messages m
      WHERE 
        m.receiver_id = ? 
        AND m.sender_id = 22  -- 系统发送
        AND m.type = 0        -- 邀请消息
        AND m.is_read = 0     -- 未读
      ORDER BY m.created_at DESC
      LIMIT 100
    `;

    // 关键修改：用 queryDb 替代 db.promise().query，无需解构 [result]
    const inviteResult = await queryDb(queryInvitesSql, [receiverId]);

    // 3. 无未读邀请时的响应（保持不变）
    if (inviteResult.length === 0) {
      return res.status(200).json({
        status: 200,
        message: "暂无未读的系统邀请",
        data: {
          inviteList: [],
          unreadCount: 0
        }
      });
    }

    // 4. 格式化未读邀请数据（保持不变）
    const inviteList = inviteResult.map(invite => ({
      inviteId: invite.inviteId,
      inviteContent: invite.inviteContent,
      isRead: invite.isRead === 1,
      sendTime: new Date(invite.sendTime).toLocaleString(),
      type: 0
    }));

    // 5. 统计未读数量（保持不变）
    const unreadCount = inviteList.length;

    // 6. 返回成功响应（保持不变）
    res.status(200).json({
      status: 200,
      message: "未读的系统邀请获取成功",
      data: {
        inviteList: inviteList,
        unreadCount: unreadCount
      }
    });

  } catch (err) {
    console.error("获取未读邀请异常:", err.stack);
    res.status(500).json({
      status: 500,
      message: "获取未读邀请失败：服务器内部错误",
      error: process.env.NODE_ENV === 'development' ? err.message : undefined
    });
  }
};
//处理邀请信息
const handleInvite = async (req, res) => {
  try {
    // 1. 解析请求参数（与原逻辑一致）
    const { inviteId, action, userId } = req.body;

    // 2. 基础参数校验（同步逻辑，直接保留）
    if (!userId) {
      return res.send({ status: 401, message: "请先登录再处理邀请" });
    }
    if (!inviteId || isNaN(Number(inviteId))) {
      return res.send({
        status: 400,
        message: "邀请ID（inviteId）不能为空且必须是有效数字"
      });
    }
    if (action !== 0 && action !== 1) {
      return res.send({
        status: 400,
        message: "处理动作（action）必须是0（拒绝）或1（同意）"
      });
    }
    const inviteIdNum = Number(inviteId);
    const receiverId = Number(userId);

    // 3. 校验邀请是否存在且未处理（异步查询，await 等待结果）
    const checkInviteSql = `
      SELECT id, content 
      FROM messages 
      WHERE id = ? 
        AND receiver_id = ? 
        AND sender_id = 22 
        AND type = 0
    `;
    const inviteResult = await queryDb(checkInviteSql, [inviteIdNum, receiverId]);
    if (inviteResult.length === 0) {
      return res.send({ status: 404, message: "邀请不存在或已处理，请刷新重试" });
    }
    const inviteContent = inviteResult[0].content;

    // 4. 提取邀请者昵称（同步逻辑，保留原正则匹配）
    const nicknameMatch = inviteContent.match(/【(.*?)】/);
    const inviterNickname = nicknameMatch ? nicknameMatch[1] : "未知用户";
    if (inviterNickname === "未知用户") {
      return res.send({ status: 400, message: "邀请信息格式错误，无法识别邀请者" });
    }

    // 5. 更新消息状态为“已读”（异步操作，await 执行）
    const updateMessageSql = `
      UPDATE messages 
      SET is_read = 1 
      WHERE id = ?
    `;
    await queryDb(updateMessageSql, [inviteIdNum]);

    // 6. 同意操作（action=1）：查邀请者ID → 校验 → 更新关系
    if (action === 1) {
      // 6.1 用唯一昵称查邀请者ID（异步查询）
      const findInviterByNicknameSql = `
        SELECT id AS inviter_id 
        FROM users 
        WHERE nickname = ?
      `;
      const inviterResult = await queryDb(findInviterByNicknameSql, [inviterNickname]);
      if (inviterResult.length === 0) {
        return res.send({ status: 404, message: `昵称【${inviterNickname}】的用户不存在，无法建立伙伴关系` });
      }
      const inviterId = inviterResult[0].inviter_id;

      // 6.2 校验：邀请者不能是自己（同步逻辑）
      if (inviterId === receiverId) {
        return res.send({ status: 400, message: "不能与自己建立伙伴关系" });
      }

      // 6.3 校验邀请状态（避免重复同意/已处理）（异步查询）
      const checkInviteStatusSql = `
        SELECT status 
        FROM partners 
        WHERE user_id = ? 
          AND partner_id = ?
      `;
      const statusResult = await queryDb(checkInviteStatusSql, [inviterId, receiverId]);
      if (statusResult.length === 0) {
        return res.send({ status: 404, message: "未找到对应的待同意邀请，无法处理" });
      }

      const inviteStatus = statusResult[0].status;
      if (inviteStatus === 1) {
        return res.send({ status: 400, message: `已与【${inviterNickname}】建立伙伴关系，无需重复同意` });
      }
      if (inviteStatus === 2) {
        return res.send({ status: 400, message: `已拒绝【${inviterNickname}】的邀请，无法再次同意` });
      }

      // 6.4 更新邀请状态为“已同意”（异步操作）
      const updatePartnerStatusSql = `
        UPDATE partners 
        SET status = 1, updated_at = CURRENT_TIMESTAMP 
        WHERE user_id = ? AND partner_id = ?
      `;
      await queryDb(updatePartnerStatusSql, [inviterId, receiverId]);

      // 6.5 插入反向伙伴关系（确保双方互见）（异步操作）
      const insertReversePartnerSql = `
        INSERT INTO partners (user_id, partner_id, status)
        VALUES (?, ?, 1)
        ON DUPLICATE KEY UPDATE status = 1
      `;
      await queryDb(insertReversePartnerSql, [receiverId, inviterId]);

      // 同意操作成功响应
      return res.send({
        status: 200,
        message: `已同意【${inviterNickname}】的邀请，成功建立伙伴关系`,
        data: {
          inviteId: inviteIdNum,
          inviterId: inviterId,
          inviterNickname: inviterNickname,
          action: 1,
          handledTime: new Date().toLocaleString()
        }
      });
    }

    // 7. 拒绝操作（action=0）：标记邀请为已拒绝
    // 7.1 用昵称查邀请者ID（异步查询）
    const findInviterByNicknameSql = `
      SELECT id AS inviter_id 
      FROM users 
      WHERE nickname = ?
    `;
    let inviterId = null;
    try {
      const inviterResult = await queryDb(findInviterByNicknameSql, [inviterNickname]);
      inviterId = inviterResult.length > 0 ? inviterResult[0].inviter_id : null;
    } catch (err) {
      // 查不到邀请者不中断，仍返回拒绝成功（保留原用户体验逻辑）
      console.error("查邀请者失败:", err.message);
    }

    // 7.2 更新邀请状态为“已拒绝”（异步操作，失败不阻塞）
    if (inviterId) {
      const updateRejectStatusSql = `
        UPDATE partners 
        SET status = 2, updated_at = CURRENT_TIMESTAMP 
        WHERE user_id = ? AND partner_id = ? AND status = 0
      `;
      try {
        await queryDb(updateRejectStatusSql, [inviterId, receiverId]);
      } catch (err) {
        console.error("标记邀请为拒绝失败:", err.message);
      }
    }

    // 拒绝操作成功响应（无论是否查到邀请者/更新成功）
    return res.send({
      status: 200,
      message: `已拒绝【${inviterNickname}】的邀请`,
      data: {
        inviteId: inviteIdNum,
        inviterNickname: inviterNickname,
        action: 0,
        handledTime: new Date().toLocaleString()
      }
    });

  } catch (err) {
    // 统一捕获所有异步错误（数据库操作失败等）
    console.error("处理邀请整体出错:", err.message);
    return res.send({
      status: 500,
      message: "处理邀请失败：系统异常，请稍后重试"
    });
  }
};
//发起邀请
const sendPartnerInvite = async (req, res) => {
  try {
    // 1. 解析请求参数（与原逻辑一致）
    const { receiverId, senderId, inviteMsg = "" } = req.body;

    // 2. 基础参数校验（同步逻辑，保留原规则）
    if (!senderId) {
      return res.send({ status: 401, message: "请先登录再发起邀请" });
    }
    if (!receiverId || isNaN(Number(receiverId))) {
      return res.send({
        status: 400,
        message: "接收邀请的用户ID（receiverId）不能为空且必须是有效数字"
      });
    }
    const receiverIdNum = Number(receiverId);
    if (senderId === receiverIdNum) {
      return res.send({ status: 400, message: "不能邀请自己成为学习伙伴" });
    }

    // 3. 校验发起者和接收者是否为有效用户（异步查询，await 等待）
    const checkUsersSql = `
      SELECT id, nickname 
      FROM users 
      WHERE id IN (?, ?)
    `;
    const userResult = await queryDb(checkUsersSql, [senderId, receiverIdNum]);
    if (userResult.length < 2) {
      console.error(userResult);
      return res.send({ status: 404, message: "接收邀请的用户不存在" });
    }
    const receiverNickname = userResult.find(u => u.id === receiverIdNum).nickname;

    // 4. 校验发起者是否完善学习偏好和课程（异步查询）
    const checkSenderInfoSql = `
      SELECT p.study_time, ucp.selected_course_names 
      FROM preferences p
      JOIN user_complete_profile ucp ON p.user_id = ucp.user_id
      WHERE p.user_id = ?
    `;
    const senderInfoResult = await queryDb(checkSenderInfoSql, [senderId]);
    const senderInfo = senderInfoResult[0];
    if (!senderInfo || !senderInfo.study_time || !senderInfo.selected_course_names) {
      return res.send({ status: 400, message: "请先完善学习偏好和添加课程" });
    }

    // 5. 校验是否存在历史邀请关系（异步查询）
    const checkInviteSql = `
      SELECT status 
      FROM partners 
      WHERE (user_id = ? AND partner_id = ?) 
         OR (user_id = ? AND partner_id = ?)
    `;
    const statusResult = await queryDb(checkInviteSql, [
      senderId, receiverIdNum, receiverIdNum, senderId
    ]);
    if (statusResult.length > 0) {
      const status = statusResult[0].status;
      if (status === 1) {
        return res.send({ status: 400, message: "该用户已成为你的伙伴" });
      } else {
        return res.send({ status: 400, message: "已发送邀请，等待对方同意" });
      }
    }

    // 6. 插入邀请记录（异步操作）
    const insertInviteSql = `
      INSERT INTO partners 
      (user_id, partner_id, status)
      VALUES (?, ?, 0)
    `;
    const insertResult = await queryDb(insertInviteSql, [senderId, receiverIdNum]);

    // 7. 插入系统通知（异步操作，失败不影响主流程，单独捕获错误）
    const noticeContent = `用户【${req.user.nickname}】邀请你成为学习伙伴：${inviteMsg || "一起学习吧！"}`;
    const insertNoticeSql = `
      INSERT INTO messages 
      (sender_id, receiver_id, type, content, is_read)
      VALUES (22, ?, 0, ?, 0)
    `;
    try {
      await queryDb(insertNoticeSql, [receiverIdNum, noticeContent]);
    } catch (err) {
      // 通知插入失败不阻塞邀请主流程，仅打印日志
      console.error("插入通知失败:", err.message);
    }

    // 8. 返回成功响应（与原格式一致）
    return res.send({
      status: 200,
      message: "邀请发送成功，等待对方同意",
      data: {
        inviteId: insertResult.insertId,
        receiverId: receiverIdNum,
        receiverNickname,
        createTime: new Date().toLocaleString()
      }
    });

  } catch (err) {
    // 统一捕获所有异步错误（数据库操作失败等）
    console.error("发送邀请异常:", err.stack);
    let errorMsg = "发送邀请失败：系统异常";
    // 根据错误场景细化提示（可选，保留原逻辑的错误上下文）
    if (err.message.includes("SELECT")) errorMsg = "发送邀请失败：查询信息出错";
    if (err.message.includes("INSERT")) errorMsg = "发送邀请失败：插入记录出错";
    return res.send({ status: 500, message: errorMsg });
  }
};
//得到聊天记录
const getChatMessages = async (req, res) => {
  try {
    // 1. 解析请求参数（与原逻辑一致）
    const { userId, partnerId } = req.query;

    // 2. 基础参数校验（同步逻辑，保留原规则）
    if (!userId || isNaN(Number(userId))) {
      return res.send({
        status: 400,
        message: "用户ID（userId）不能为空且必须是有效数字"
      });
    }
    if (!partnerId || isNaN(Number(partnerId))) {
      return res.send({
        status: 400,
        message: "聊天对象ID（partnerId）不能为空且必须是有效数字"
      });
    }
    const currentUserId = Number(userId);
    const targetUserId = Number(partnerId);
    if (currentUserId === targetUserId) {
      return res.send({ status: 400, message: "不能与自己聊天" });
    }

    // 3. 校验双方是否为有效用户（异步查询）
    const checkUsersSql = `
      SELECT id 
      FROM users 
      WHERE id IN (?, ?)
    `;
    const userResult = await queryDb(checkUsersSql, [currentUserId, targetUserId]);
    if (userResult.length < 2) {
      return res.send({ status: 404, message: "聊天对象不存在" });
    }

    // 4. 校验双方是否为伙伴关系（异步查询）
    const checkPartnerSql = `
      SELECT id 
      FROM partners 
      WHERE (user_id = ? AND partner_id = ? AND status = 1)
         OR (user_id = ? AND partner_id = ? AND status = 1)
    `;
    const partnerResult = await queryDb(checkPartnerSql, [
      currentUserId, targetUserId, targetUserId, currentUserId
    ]);
    if (partnerResult.length === 0) {
      return res.send({ status: 403, message: "仅能查看伙伴的聊天记录，请先建立伙伴关系" });
    }

    // 5. 查询聊天记录（异步查询，按id升序排序）
    const queryChatSql = `
      SELECT 
        id AS messageId,
        sender_id AS senderId,
        receiver_id AS receiverId,
        content,
        created_at AS time,
        is_read AS isRead
      FROM messages 
      WHERE 
        ((sender_id = ? AND receiver_id = ?)  
        OR (sender_id = ? AND receiver_id = ?))
        AND type = 1  -- 仅聊天消息
        AND is_withdrawn = 0      -- 未撤回
      ORDER BY id ASC  -- 按自增id排序（性能更优）
      LIMIT 100
    `;
    const chatResult = await queryDb(queryChatSql, [
      currentUserId, targetUserId, targetUserId, currentUserId
    ]);

    // 6. 格式化聊天记录（与原逻辑一致）
    const chatList = chatResult.map(msg => ({
      senderId: msg.senderId,
      messageId: msg.messageId,
      content: msg.content,
      time: new Date(msg.time).toLocaleTimeString([], { 
        hour: '2-digit', 
        minute: '2-digit',
        hour12: false 
      }),
      isMe: msg.senderId === currentUserId, // 是否为当前用户发送的消息
      isRead: msg.isRead === 1
    }));

    // 7. 标记未读消息为已读（异步操作，失败不影响主流程）
    const unreadIds = chatResult
      .filter(msg => msg.isRead === 0 && msg.receiver_id === currentUserId) // 仅标记当前用户接收的未读消息
      .map(msg => msg.messageId);
    
    if (unreadIds.length > 0) {
      const markReadSql = `
        UPDATE messages 
        SET is_read = 1 
        WHERE id IN (${unreadIds.join(',')})
      `;
      try {
        await queryDb(markReadSql);
      } catch (err) {
        // 标记已读失败不阻塞聊天记录返回，仅打印日志
        console.error("标记聊天消息已读失败:", err.message);
      }
    }
    // 8. 返回成功响应（与原格式一致）
    return res.send({
      status: 200,
      message: "聊天记录获取成功",
      data: {
        chatList: chatList,
        total: chatList.length,
        partnerId: targetUserId,
        unreadCount: 0 // 已标记所有未读为已读，未读数量置0
      }
    });

  } catch (err) {
    // 统一捕获所有异步错误（数据库操作失败等）
    console.error("获取聊天记录异常:", err.stack);
    let errorMsg = "获取聊天记录失败：系统异常";
    // 细化错误提示（可选）
    if (err.message.includes("SELECT")) errorMsg = "获取聊天记录失败：查询信息出错";
    if (err.message.includes("UPDATE")) errorMsg = "获取聊天记录失败：标记已读出错";
    return res.send({ status: 500, message: errorMsg });
  }
};
// 发送聊天消息
const sendChatMessage = async (req, res) => {
  try {
    // 1. 解析请求体参数（与原逻辑一致）
    const { senderId, receiverId, content, type } = req.body;

    // 2. 基础参数校验（同步逻辑，保留原所有规则）
    // 2.1 校验发送者ID
    if (!senderId || isNaN(Number(senderId))) {
      return res.send({
        status: 400,
        message: "发送者ID（senderId）不能为空且必须是有效数字"
      });
    }
    // 2.2 校验接收者ID
    if (!receiverId || isNaN(Number(receiverId))) {
      return res.send({
        status: 400,
        message: "接收者ID（receiverId）不能为空且必须是有效数字"
      });
    }
    // 2.3 校验消息内容（去空格后非空）
    const trimmedContent = content?.trim();
    if (!trimmedContent) {
      return res.send({
        status: 400,
        message: "消息内容不能为空"
      });
    }
    // 2.4 校验消息类型（固定为1=聊天消息）
    if (type !== 1) {
      return res.send({
        status: 400,
        message: "聊天消息类型错误（type必须为1）"
      });
    }
    // 2.5 禁止给自己发消息
    const senderIdNum = Number(senderId);
    const receiverIdNum = Number(receiverId);
    if (senderIdNum === receiverIdNum) {
      return res.send({
        status: 400,
        message: "不能给自己发送聊天消息"
      });
    }

    // 3. 校验发送者和接收者是否为有效用户（异步查询）
    const checkUsersSql = `
      SELECT id 
      FROM users 
      WHERE id IN (?, ?)
    `;
    const userResult = await queryDb(checkUsersSql, [senderIdNum, receiverIdNum]);
    if (userResult.length < 2) {
      return res.send({
        status: 404,
        message: "接收消息的伙伴不存在"
      });
    }

    // 4. 校验双方是否为伙伴关系（异步查询，与getChatMessages逻辑对齐）
    const checkPartnerSql = `
      SELECT id 
      FROM partners 
      WHERE (user_id = ? AND partner_id = ? AND status = 1)
         OR (user_id = ? AND partner_id = ? AND status = 1)
    `;
    const partnerResult = await queryDb(checkPartnerSql, [
      senderIdNum, receiverIdNum, receiverIdNum, senderIdNum
    ]);
    if (partnerResult.length === 0) {
      return res.send({
        status: 403,
        message: "仅能给伙伴发送消息，请先建立伙伴关系"
      });
    }

    // 5. 插入聊天消息到messages表（异步操作，核心逻辑）
    const insertMessageSql = `
      INSERT INTO messages 
      (sender_id, receiver_id, type, content, is_read, created_at)
      VALUES (?, ?, ?, ?, 0, CURRENT_TIMESTAMP)
    `;
    const insertResult = await queryDb(insertMessageSql, [
      senderIdNum, receiverIdNum, type, trimmedContent
    ]);

    // 6. 成功响应（与原格式一致，保持接口响应风格统一）
    return res.send({
      status: 200,
      message: "聊天消息发送成功",
      data: {
        messageId: insertResult.insertId, // 消息自增ID（供前端追踪）
        senderId: senderIdNum,
        receiverId: receiverIdNum,
        content: trimmedContent,
        sendTime: new Date().toLocaleString(), // 本地化发送时间
        type: 1 // 明确聊天消息类型
      }
    });

  } catch (err) {
    // 统一捕获所有异步错误（数据库操作失败等）
    console.error("发送聊天消息异常:", err.stack);
    let errorMsg = "发送消息失败：系统异常";
    // 细化错误提示（与原逻辑的错误场景对应）
    if (err.message.includes("SELECT")) errorMsg = "发送消息失败：查询信息出错";
    if (err.message.includes("INSERT")) errorMsg = "发送消息失败：保存消息到数据库出错";
    return res.send({ status: 500, message: errorMsg });
  }
};
//撤回聊天记录
const chatWithdraw = async (req, res) => {
  try {
    // 1. 解析请求参数（撤回者ID、消息ID，支持body传参）
    const { sender_id, id } = req.body;

    // 2. 严格参数校验（非空+数字格式，与其他聊天接口校验逻辑一致）
    if (!sender_id || isNaN(Number(sender_id))) {
      return res.status(400).json({
        status: 400,
        message: "参数错误：用户ID（userId）不能为空且必须为有效数字"
      });
    }
    if (!id  || isNaN(Number(id ))) {
      return res.status(400).json({
        status: 400,
        message: "参数错误：消息ID（messageId）不能为空且必须为有效数字"
      });
    }
    const withdrawUserId = Number(sender_id);
    const targetMessageId = Number(id);

    // 3. 校验：消息是否存在 + 消息发送者是否为当前用户 
    // 关联messages表，确保仅能撤回自己发送的聊天消息（type=1）
    const checkMessageSql = `
      SELECT id, sender_id, created_at
      FROM messages
      WHERE id = ? 
        AND sender_id = ? 
        AND is_withdrawn = 0
    `;
    const messageResult = await queryDb(checkMessageSql, [targetMessageId, withdrawUserId]);

    // 3.1 消息不存在/不属于当前用户/已撤回
    if (messageResult.length === 0) {
      return res.status(404).json({
        status: 404,
        message: "无法撤回：消息不存在、已撤回或你无权限撤回该消息"
      });
    }

    // 3.2 可选：添加撤回时间限制（如发送后5分钟内可撤回，按需开启）
    const messageCreateTime = new Date(messageResult[0].created_at);
    const now = new Date();
    const withdrawLimit = 2 * 60 * 1000; // 5分钟（毫秒）
    if (now - messageCreateTime > withdrawLimit) {
      return res.status(400).json({
        status: 400,
        message: "消息发送超过2分钟，无法撤回"
      });
    }

    // 4. 执行撤回操作（逻辑删除：更新is_withdrawn为1，保留消息记录）
    const withdrawSql = `
      UPDATE messages
      SET is_withdrawn = 1 
      WHERE id = ? AND sender_id = ?
    `;
    const updateResult = await queryDb(withdrawSql, [targetMessageId, withdrawUserId]);

    // 5. 验证撤回结果（理论上不会走到，因前面已校验消息存在）
    if (updateResult.affectedRows === 0) {
      return res.status(500).json({
        status: 500,
        message: "撤回失败：更新消息状态出错"
      });
    }

    // 6. 返回成功响应（与其他聊天接口响应格式一致）
    res.status(200).json({
      status: 200,
      message: "消息撤回成功",
      data: {
        messageId: targetMessageId,
        withdrawUserId: withdrawUserId,
        withdrawTime: new Date().toISOString(),
        isWithdrawn: true
      }
    });

  } catch (err) {
    // 7. 错误处理（与其他接口风格统一，区分开发/生产环境）
    console.error("撤回消息异常:", err.stack);
    res.status(500).json({
      status: 500,
      message: "撤回消息失败：服务器内部错误",
      error: process.env.NODE_ENV === 'development' ? err.message : undefined
    });
  }
};
//删除伙伴
const deletePartner = async (req, res) => {
  try {
    // 1. 参数校验（保持原有规则不变）
    const { userId, partnerId } = req.body;
    if (
      !userId || isNaN(Number(userId)) ||
      !partnerId || isNaN(Number(partnerId))
    ) {
      return res.status(400).json({
        status: 400,
        message: "参数错误：用户ID和伙伴ID不能为空且必须为数字"
      });
    }

    const targetUserId = Number(userId);
    const targetPartnerId = Number(partnerId);

    // 2. 禁止删除自己（保持原有逻辑）
    if (targetUserId === targetPartnerId) {
      return res.status(400).json({
        status: 400,
        message: "无法删除自己：不能将自己从伙伴列表中移除"
      });
    }

    // 3. 校验：伙伴关系是否存在（改用 queryDb，无需解构 [result]）
    const checkRelationSql = `
      SELECT id FROM partners
      WHERE user_id = ? AND partner_id = ? AND status = 1
      LIMIT 1
    `;
    // 关键修改：用 queryDb 替代 db.promise().query，直接接收 result
    const relationResult = await queryDb(checkRelationSql, [targetUserId, targetPartnerId]);

    // 4. 处理“伙伴关系不存在”场景（保持不变）
    if (relationResult.length === 0) {
      return res.status(400).json({
        status: 400,
        message: "无法删除：该伙伴关系不存在或未建立"
      });
    }

    // 5. 执行删除：移除当前用户→目标伙伴的关系（改用 queryDb）
    const deleteRelationSql = `
      DELETE FROM partners
      WHERE user_id = ? AND partner_id = ? AND status = 1
    `;
    const deleteResult = await queryDb(deleteRelationSql, [targetUserId, targetPartnerId]);

    // 6. 验证删除结果（保持不变）
    if (deleteResult.affectedRows === 0) {
      return res.status(500).json({
        status: 500,
        message: "删除失败：未找到可删除的伙伴关系"
      });
    }

    // 7. 执行反向删除：移除目标伙伴→当前用户的关系（改用 queryDb）
    const deleteReverseRelationSql = `
      DELETE FROM partners
      WHERE user_id = ? AND partner_id = ? AND status = 1
    `;
    await queryDb(deleteReverseRelationSql, [targetPartnerId, targetUserId]);

    // 8. 返回成功响应（保持原有格式）
    return res.status(200).json({
      status: 200,
      message: "删除伙伴成功",
      data: {
        userId: targetUserId,
        deletedPartnerId: targetPartnerId
      }
    });

  } catch (err) {
    // 9. 错误处理（与其他接口风格一致）
    console.error("删除伙伴异常:", err.stack);
    res.status(500).json({
      status: 500,
      message: "删除伙伴失败：服务器内部错误",
      error: process.env.NODE_ENV === 'development' ? err.message : undefined
    });
  }
};

module.exports={
  sendPartnerInvite,
  getPartnerInfo,
  getInviteInfo,
  handleInvite,
  getChatMessages,
  sendChatMessage,
  chatWithdraw,
  deletePartner
}